package ee.ut.re;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;

public class ArffConverter {

	
	File inFile;
	File outFile;
	
	public ArffConverter() {
		
	}
	
	public void convert(File mysqlFile, File outFile) throws IOException {
		LineIterator it = FileUtils.lineIterator(mysqlFile, "UTF-8");
		boolean started = false;
		
		SortedSet<String> fields = new TreeSet<String>();
		//fields.add("AREA_SIZE_ALL");
		//fields.add("OBJECTTYPE");
		fields.add("KIRJELDUS_SAUN");
		fields.add("KIRJELDUS_RODU");
		fields.add("KIRJELDUS_YLDPIND");
		
		
		OutputStream outStream = new BufferedOutputStream(new FileOutputStream(outFile));
		
		writeHeader(outStream);
		
		Map<String, Integer> fieldMap = null;
		int cnt = 0;
		try {
			while (it.hasNext()) {
				String line = it.next();
				if (!started) {
					if (line.startsWith("INSERT INTO")) {
						started = true;
						
						fieldMap = extractFieldMap(line);
						outStream.write("@DATA\n".getBytes());
						continue;
					}
					continue;
				}
				
				SortedMap<String, String> keyFields = extractKeyFields(fieldMap, fields, splitLine(line, fieldMap.size()));
				outStream.write(observationRow(keyFields));
				outStream.write('\n');
				if (cnt++ > 10) {
				break;
				}
			}
		} finally {
			it.close();
			outStream.flush();
			outStream.close();
		}
		
		
	}

	private byte[] observationRow(SortedMap<String, String> keyFields) {
		StringBuffer sb = new StringBuffer();
		boolean first = true;
		for(Map.Entry<String, String> entry : keyFields.entrySet()) {
			if (first) {
				first = false;
			} else {
				sb.append(',');
			}
			sb.append(entry.getValue());
			
		}
		return sb.toString().getBytes();
	}

	private void writeHeader(OutputStream outStream) {
		try {
			outStream.write("@RELATION korter\n".getBytes("UTF-8"));
			outStream.write("@ATTRIBUTE KIRJELDUS_SAUN NUMERIC\n".getBytes("UTF-8"));
			outStream.write("@ATTRIBUTE KIRJELDUS_RODU NUMERIC\n".getBytes("UTF-8"));
			outStream.write("@ATTRIBUTE KIRJELDUS_YLDPIND NUMERIC\n\n".getBytes("UTF-8"));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		
	}

	private List<String> splitLine(String line, int cnt) {
		line = line.substring(1, line.length()-2);
		Pattern pattern = Pattern.compile("(\\d+|'.*?')");
		
		List<String> out = new ArrayList<String>();
		for (int i = 0; i < cnt; i++) {
			Matcher matcher = pattern.matcher(line);
			if (matcher.find()){
				String m = matcher.group(1);
				out.add(m);
				line = line.replaceFirst(m, "");
				line = line.substring(2);
			} 
		}
	
		return out;
	}

	private SortedMap<String, String> extractKeyFields(Map<String, Integer> fieldMap,
			Set<String> fields, List<String> values) {
		
		SortedMap<String,String> out = new TreeMap<String,String>();
		
		for (String f : fields) {
			out.put(f, values.get(fieldMap.get(f)));
		}
		
		return out;
	}

	/**
	 * @param line
	 * @return Map of field name to line entry index.
	 */
	private Map<String, Integer> extractFieldMap(String line) {
		line = line.replace("INSERT INTO `city2` (", "");
		line = line.replace(") VALUES", "");
		
		Map<String, Integer> out = new HashMap<String, Integer>();
		
		int i = 0;
		for(String name : line.split(",")) {
			name = name.replaceAll("`", "");
			name = name.trim();
			out.put(name, i++);
		} 
		
		
		return out;
	}

	public static void main(String args[]) throws IOException {
		ArffConverter converter = new ArffConverter();
		converter.convert(new File(args[0]), new File(args[1]));
	}
	
	
}
